/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ejb;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.SortedSet;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.persistence.TemporalType;

/**
 *
 * @author Cuchu
 */
@Stateless
public class RecensioneInternaFacade extends AbstractFacade<RecensioneInterna> implements RecensioneInternaFacadeLocal {

    @EJB
    private PiattaformaFacadeLocal piattaformaFacade;
    @PersistenceContext(unitName = "EnterpriseApplication12-13-ejbPU")
    private EntityManager em;

    @Override
    protected EntityManager getEntityManager() {
        return em;
    }

    public RecensioneInternaFacade() {
        super(RecensioneInterna.class);
    }
    /**
     * Cerca la RecensioneInterna nel Database
     *
     * @param r RecensioneInterna da cercare
     * @return true se la RecensioneInterna e' presente nel Database, false altrimenti
     */
    @Override
    public boolean esistente(RecensioneInterna r) {
        String s = "select ri from RecensioneInterna ri where ri.titolo=?1 ";
        Query q = em.createQuery(s).setParameter(1, r.getTitolo());
        return !(q.getResultList().isEmpty());
    }

    /**
     * Cerca la RecensioneInterna con uno specifico titolo nel Database
     *
     * @param titolo il titolo della RecensioneInterna da cercare
     * @return RecensioneInterna la RecensioneInterna con il specifico titolo, null altrimenti
     */
    @Override
    public RecensioneInterna find(Object titolo) {

        String s = "select ri from RecensioneInterna ri where ri.titolo=?1 ";
        Query q = em.createQuery(s).setParameter(1, titolo);
        if (q.getResultList().isEmpty()) {
            return null;
        }
        return (RecensioneInterna) q.getSingleResult();
    }
    /**
     * Trova tutte le RecensioneInterne presente nel Database
     *
     * @param text sottostringa da cercare nei testi delle RecensioneInterne presenti nel Database
     * @return Elenco delle RecensioneInterne, altrimenti restituisce una lista vuota
     */
    @Override
    public List<RecensioneInterna> contains(String text) throws FileNotFoundException, IOException {

        List<RecensioneInterna> recensioni;
        String uri;
        FileInputStream fstream;
        DataInputStream in;
        BufferedReader br;
        String strLine;
        text = text.toLowerCase();
        ArrayList<String> ric = new ArrayList<String>(Arrays.asList(text.split(" ")));
        ArrayList<RecensioneInterna> risposta = new ArrayList<RecensioneInterna>();
        //if(ric.size() == 1)throw new IOException("Errore!! la stringa dovrebbe essere lunga almeno 4 caratteri ");
        //if((ric == null)|| (ric.isEmpty()))throw new IOException("Errore!! la stringa dovrebbe essere lunga almeno 4 caratteri ");
       for(int i=0;i<ric.size();i++){
           if(ric.get(i).length()<4){
              ric.remove(i);
              i--;
           }
       
       }
        
        /*for (String r : ric) {
            if (r.length() < 4) {
                ric.remove(r);
            }
        }*/
        if (ric.isEmpty())throw new IOException("Errore!! la stringa dovrebbe essere lunga almeno 4 caratteri ");
        ArrayList<String> aus;
        String sql = "select ri from RecensioneInterna ri order by ri.dataPubblicazione";
        Query q = em.createQuery(sql);
        recensioni = q.getResultList();
        int i;
        for (RecensioneInterna r : recensioni) {
            uri = r.getTesto();
            fstream = new FileInputStream(uri);
            in = new DataInputStream(fstream);
            br = new BufferedReader(new InputStreamReader(in));

            aus = (ArrayList<String>) ric.clone();
            while (((strLine = br.readLine()) != null) && (!aus.isEmpty())) {
                i = 0;
                while (i < aus.size() && (!aus.isEmpty())) {
                    //if (strLine.toLowerCase().contains(aus.get(i))){
                    if (like(strLine, ("%" + aus.get(i).toUpperCase() + "%"))|| like(r.getTitolo(),("%" + aus.get(i).toUpperCase() + "%"))) {

                        aus.remove(aus.get(i));
                    } else {
                        i++;
                    }
                }
            }
            if (aus.isEmpty()) {
                risposta.add(r);
            }
            //se non è presente nei risultati e trovo che il testo passato 
            //è il titolo lo aggiungo
            RecensioneInterna ri = find(text);
            if (ri != null && !risposta.contains(ri)) {
                risposta.add(ri);
            }
            br.close();
            in.close();
            fstream.close();
        }

        return risposta;

    }

    /**
     * ****** Metodo ausiliario like che ha lo stesso funzionamento
     * dell'operatore LIKE di SQL **********
     */
    public static boolean like(String toBeCompare, String by) {
        if (by != null) {
            if (toBeCompare != null) {
                if (by.startsWith("%") && by.endsWith("%")) {
                    int index = toBeCompare.toLowerCase().indexOf(by.replace("%", "").toLowerCase());
                    if (index < 0) {
                        return false;
                    } else {
                        return true;
                    }
                } else if (by.startsWith("%")) {
                    return toBeCompare.endsWith(by.replace("%", ""));
                } else if (by.endsWith("%")) {
                    return toBeCompare.startsWith(by.replace("%", ""));
                } else {
                    return toBeCompare.equals(by.replace("%", ""));
                }
            } else {
                return false;
            }
        } else {
            return false;
        }
    }
    /**
     * Trova tutte le RecensioneInterne presente nel Database
     *
     * @param titolo sottostringa da cercare tra tutti i titoli delle RecensioneInterne
     * presenti nel Database
     * @param text sottostringa da cercare nei testi delle RecensioneInterne presenti nel
     * Database
     * @param platforms lista dei nomi delle piattaforme da cercare tra tutte le piattaforme delle
     * RecensioneInterne presente nel Database
     * @param data data della pubblicazione delle RecensioneInterne da cercare
     * @return Elenco delle RecensioneInterne, altrimenti restituisce una lista vuota
     */
    @Override
    public List<RecensioneInterna> findSome(String titolo, String text, List<String> platforms, String data) throws FileNotFoundException, IOException {
        //uso un set perchè i duplicati almeno non li tengo
        Set<RecensioneInterna> result = new HashSet<RecensioneInterna>();
        //ricerca per titolo
        if (titolo != null) {
            RecensioneInterna ri = find(titolo);
            if (ri != null) {
                result.add(ri);
            }
        }
        //ricerca per piattaforma
        if (platforms != null) {
            Piattaforma p;
            
            for (String nome:platforms){
                p= piattaformaFacade.esiste(nome);
                long idP;
                if (p != null) {
                    idP = p.getId();
                    String query = "SELECT r.* FROM RecensioneInterna r, RECENSIONEINTERNA_VIDEOGAME rv, videogame v,piattaforma p "
                        + "WHERE  r.id = rv.recensioneinterna_ID AND rv.videogiochi_ID = v.id AND p.ID=?1 AND v.piattaforma_ID = p.ID order by r.dataPubblicazione" ;
                    List<RecensioneInterna> parz = (List<RecensioneInterna>)em.createNativeQuery(query,RecensioneInterna.class).setParameter(1, idP).getResultList();
                    result.addAll(parz);
                }
            }
        }
        //ricerca per testo 
        if (text != null) {
            List<RecensioneInterna> parz = contains(text);
            result.addAll(parz);
        }
        //costruisco la lista dall'insieme risultato
        List<RecensioneInterna> r = new ArrayList<RecensioneInterna>();
        r.addAll(result);
        return r;
    }
    /**
     * Cerca la RecensioneInterna con uno specifico id nel Database
     *
     * @param id l'identificativo della RecensioneInterna da cercare
     * @return RecensioneInterna la RecensioneInterna con il specifico id, null altrimenti
     */
    @Override
    public RecensioneInterna find(long id) {
        String s = "select ri from RecensioneInterna ri where ri.id=?1 ";
        Query q = em.createQuery(s).setParameter(1, id);
        if (q.getResultList().isEmpty()) {
            return null;
        }
        return (RecensioneInterna) q.getSingleResult();
    }
    
    
    @Override
    public List<RecensioneInterna> findAll(){
    String s="select r from RecensioneInterna r order by r.dataPubblicazione";
    Query q=em.createQuery(s);
    return q.getResultList();
    }
}
